#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "cardOnShowQLabel.h"
#include <QTcpServer>
#include <QTcpSocket>
#include <QMessageBox>
#include <stdlib.h>
#include <time.h>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    setFixedSize(width,height);

    textOnShow=new QLabel(this);
    textOnShow->setGeometry(width/2-textWidth/2,textPaddingTop,textWidth,textHeight);
    textOnShow->setText("");

    ui->pushButton->setGeometry(width/2-buttonWidth/2,buttonPaddingTop,buttonWidth,buttonHeight);

    beDiZhu=new QPushButton(this);
    beDiZhu->setStyleSheet("font-size:40px;");
    beDiZhu->setGeometry(width/2-buttonWidth-buttonPadding/2,buttonPaddingTop,buttonWidth,buttonHeight);
    beDiZhu->setText("叫地主");
    beDiZhu->hide();

    notDiZhu=new QPushButton(this);
    notDiZhu->setStyleSheet("font-size:40px;");
    notDiZhu->setGeometry(width/2+buttonPadding/2,buttonPaddingTop,buttonWidth,buttonHeight);
    notDiZhu->setText("不叫");
    notDiZhu->hide();

    restart=new QPushButton(this);
    restart->setStyleSheet("font-size:40px;");
    restart->setGeometry(width/2-buttonWidth-buttonPadding/2,buttonPaddingTop,buttonWidth,buttonHeight);
    restart->setText("重开");
    restart->hide();

    chuPai=new QPushButton(this);
    chuPai->setStyleSheet("font-size:40px;");
    chuPai->setGeometry(width/2-buttonWidth-buttonPadding/2,buttonPaddingTop,buttonWidth,buttonHeight);
    chuPai->setText("出牌");
    chuPai->hide();

    buChu=new QPushButton(this);
    buChu->setStyleSheet("font-size:40px;");
    buChu->setGeometry(width/2+buttonPadding/2,buttonPaddingTop,buttonWidth,buttonHeight);
    buChu->setText("不出");
    buChu->hide();

    quit=new QPushButton(this);
    quit->setStyleSheet("font-size:40px;");
    quit->setGeometry(width/2+buttonPadding/2,buttonPaddingTop,buttonWidth,buttonHeight);
    quit->setText("退出");
    quit->hide();

    connect(quit,SIGNAL(clicked()),this,SLOT(quitSlot()));

    playerLabels[0]=new ClientQLabel(this,playerPadding);
    playerLabels[1]=new ClientQLabel(this,width-playerPadding-playerLabelWidth);

    for(int i=0;i<3;i++){
        dizhu_card_labels[i]=new LabeledCard(this,dizhu_cards[i]);
        dizhu_card_labels[i]->label->setGeometry(beginForDiZhuCards+(cardWidth+cardPadding)*i,
                                                 cardPadding+playerPadding,cardWidth,cardHeight);
        dizhu_card_labels[i]->label->hide();
    }

    QMessageBox::StandardButton rb=QMessageBox::question(this,"选择模式","以房主身份开始游戏？",
                                                         QMessageBox::Yes | QMessageBox::No);
    if(rb==QMessageBox::No){initForClient();return;}

    startConnect=new QPushButton(this);
    startConnect->setGeometry(width/2-buttonWidth/2,buttonPaddingTop,buttonWidth,buttonHeight);
    startConnect->setStyleSheet("font-size:40px;");
    startConnect->setText("开始连接");

    // 没有关乎到组件的初始化的操作都交给init()，因为可能会有重开操作
    init();
    state=MainWindow::waiting;
    clients[0]=(clients[1]=nullptr);

    connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(beginGameSlot()));
    connect(beDiZhu,SIGNAL(clicked()),this,SLOT(jiaoDiZhu()));
    connect(notDiZhu,SIGNAL(clicked()),this,SLOT(buJiao()));
    connect(restart,SIGNAL(clicked()),this,SLOT(restartSlot()));
    connect(chuPai,SIGNAL(clicked()),this,SLOT(chuPaiSlot()));
    connect(buChu,SIGNAL(clicked()),this,SLOT(buChuSlot()));
    connect(startConnect,SIGNAL(clicked()),this,SLOT(startConnectSlot()));
}

void MainWindow::startConnectSlot(){
    startConnect->hide();

    server=new QTcpServer();
    if(!server->listen(QHostAddress::LocalHost,port)){
        QMessageBox::information(this, "网络连接错误", "监听端口失败，请重新运行", QMessageBox::Ok);
        exit(0);
    }

    connect(server, SIGNAL(newConnection()), this, SLOT(receiveNewConnect()));
}

void MainWindow::jiaoDiZhu(){
    beDiZhu->hide();
    notDiZhu->hide();

    textOnShow->setText("叫地主");
    textOnShow->show();

    diZhu[0]=true;

    for(int i=0;i<2;i++)
        clients[i]->write("jiao 0;");

    player_next();
    dealDiZhu(true);
}

void MainWindow::buJiao(){
    beDiZhu->hide();
    notDiZhu->hide();

    textOnShow->setText("不叫");
    textOnShow->show();

    diZhu[0]=false;

    for(int i=0;i<2;i++)
        clients[i]->write("jiao 0;");

    player_next();
    dealDiZhu(true);
}

void MainWindow::disconnectForClient(){
    QMessageBox::information(this,"网络错误","网络连接断开！程序将退出",QMessageBox::Ok);
    exit(0);
}

void MainWindow::dealAllForClient(){
    QList<QString> argss=(QString(client->readAll())).split(';');

    qDebug()<<argss;

    for(auto command:argss){
        auto args=command.split(' ');
        if(state==MainWindow::for_ready){
            if(args[0]==QString("index")){
                index_client=args[1].toInt();
            }else if(args[0]==QString("ready")){
                another_ready=!another_ready;
                if(another_ready){
                    playerLabels[1]->setName(QString("玩家2")+'\n'+"已准备");
                }else playerLabels[1]->setName(QString("玩家2")+'\n'+"未准备");

                playerLabels[1]->hideNum();
                playerLabels[1]->show();
            }else if(args[0]==QString("player")){
                another=!another;

                playerLabels[1]->setName(QString("玩家2")+'\n'+"未准备");
                playerLabels[1]->hideNum();

                another_ready=false;

                if(another){
                    playerLabels[1]->show();
                }else playerLabels[1]->hide();
            }else if(args[0]==QString("forDiZhu")){
                state=MainWindow::for_dizhu;

                readyButton->hide();
            }
        }else if(state==MainWindow::for_dizhu){
            if(args[0]=="canBeDiZhu"){
                beDiZhu->show();
                notDiZhu->show();
            }else if(args[0]=="jiao"){
                int which=args[1].toInt();
                if(!which){
                    playerLabels[0]->setName(QString("房主")+'\n'+"叫地主");
                }else playerLabels[1]->setName(QString("玩家2")+'\n'+"叫地主");
            }else if(args[0]=="buJiao"){
                int which=args[1].toInt();
                if(!which){
                    playerLabels[0]->setName(QString("房主")+'\n'+"不叫");
                }else playerLabels[1]->setName(QString("玩家2")+'\n'+"不叫");
            }else if(args[0]=="addCard"){
                int what=args[1].toInt();
                cards.push_back(Card(0,what));
            }else if(args[0]=="end"){
                std::sort(cards.begin(),cards.end());
                show_my_cards();
            }else if(args[0]=="diZhuCard"){
                //QMessageBox::information(this,"debug","diZhuCard",QMessageBox::Ok);

                for(int i=0;i<3;i++){
                    dizhu_cards[i]=Card(0,args[i+1].toInt());
                    dizhu_card_labels[i]->card=dizhu_cards[i];
                }

                show_dizhu_cards_hidden();
            }else if(args[0]=="diZhuIs"){
                dizhu=args[1].toInt();
                addDiZhuCards();
                state=MainWindow::gaming;
                setupGamingUI();
            }
        }else if(state==MainWindow::gaming){
            if(args[0]=="chuPai"){
                int flag=args[1].toInt();

                if(!flag)buChu->show();
                else{
                    delete lastCards;
                    lastCards=nullptr;
                }
                chuPai->show();
            }else if(args[0]=="end"){
                winner_dizhu=args[1].toInt();
                end(false);
            }else if(args[0]=="setNum"){
                if(args[1].toInt())playerLabels[1]->setNum(args[2].toInt());
                else playerLabels[0]->setNum(args[2].toInt());
            }else if(args[0]=="setCard"){
                hideBuChu();
                std::vector<Card> a;
                for(int i=1;i<args.size();i++)
                    if(args[i].size())
                        a.emplace_back(Card(0,args[i].toInt()));

                delete centerCards;
                centerCards=new CardOnShowQLabel(this,a);

                delete lastCards;
                lastCards=new Cards(std::move(a));
            }else if(args[0]=="buChu"){
                if(args[1].toInt()){
                    playerLabels[1]->showBuChu();
                }else playerLabels[0]->showBuChu();
            }
        }else if(state==MainWindow::ended){
            if(args[0]=="restart"){
                state=MainWindow::for_dizhu;
                initForClient();
            }
        }
    }
}

void MainWindow::initForClient(){
    cards.clear();

    another_ready=false;
    readied=false;

    delete centerCards;
    centerCards=nullptr;

    delete lastCards;
    lastCards=nullptr;

    textOnShow->hide();
    buChu->hide();
    chuPai->hide();

    if(client==nullptr){
        client=new QTcpSocket;

        state=MainWindow::waiting;
        for(int i=0;i<2;connected[i++]=false);
        another=false;

        if(connectButton==nullptr){
            connectButton=new QPushButton(this);
            connectButton->setStyleSheet("font-size:40px;");
            connectButton->setText("请求连接");
            connectButton->setGeometry(width/2-buttonWidth/2,buttonPaddingTop,buttonWidth,buttonHeight);
            connect(connectButton,SIGNAL(clicked()),this,SLOT(connectForClient()));
        }

        connect(client,SIGNAL(connected()),this,SLOT(connectedForClient()));
        connect(client,SIGNAL(readyRead()),this,SLOT(dealAllForClient()));
        connect(client,SIGNAL(disconnected()),this,SLOT(disconnectForClient()));
        //client->connectToHost(QHostAddress::LocalHost,port);

        connectButton->show();
        connect(chuPai,SIGNAL(clicked()),this,SLOT(chuPaiForClient()));
        connect(buChu,SIGNAL(clicked()),this,SLOT(buChuForClient()));
        connect(beDiZhu,SIGNAL(clicked()),this,SLOT(jiaoDiZhuForClient()));
        connect(notDiZhu,SIGNAL(clicked()),this,SLOT(buJiaoForClient()));

        connect(restart,SIGNAL(clicked()),this,SLOT(restartForClient()));
    }else{
        readyButton->hide();
        another=true;
        playerLabels[0]->hideNum();
        playerLabels[0]->setName("房主");
        playerLabels[1]->hideNum();
        playerLabels[1]->setName("玩家2");
    }
}

void MainWindow::restartForClient(){
    qDebug()<<"in restartforclient...";
    restart->hide();
    quit->hide();

    client->write("restart;");
}

void MainWindow::connectForClient(){
    if(state!=MainWindow::waiting)return;

    client->connectToHost(QHostAddress::LocalHost,port);
}

void MainWindow::connectedForClient(){
    if(state!=MainWindow::waiting)return;

    state=MainWindow::for_ready;
    connectButton->hide();

    if(readyButton==nullptr){
        readyButton=new QPushButton(this);
        readyButton->setStyleSheet("font-size:40px;");
        readyButton->setGeometry(width/2-buttonWidth/2,buttonPaddingTop,buttonWidth,buttonHeight);
        connect(readyButton,SIGNAL(clicked()),this,SLOT(readyForClient()));
        readyButton->show();
    }

    readyButton->setText("准备");

    playerLabels[0]->setName("房主");
    playerLabels[0]->hideNum();
    playerLabels[0]->show();
}

void MainWindow::readyForClient(){
    if(state!=MainWindow::for_ready)return;

    const char* content="ready;";
    client->write(content,strlen(content));

    readied=!readied;
    if(readied){
        readyButton->setText("取消准备");
    }else readyButton->setText("准备");
}

void MainWindow::init(){
    // 一些常量的归位
    is_ready[0]=true;
    for(int i=1;i<3;is_ready[i++]=false);
    for(int i=0;i<3;diZhu[i++]=false);
    for(int i=0;i<2;connected[i++]=false);
    index_client=0;

    delete centerCards;
    centerCards=nullptr;

    delete lastCards;
    lastCards=nullptr;

    chuPai->hide();
    buChu->hide();

    // 地主牌隐藏。无需设置内容为空，因为这是在展示地主牌的函数做的
    for(auto i:dizhu_card_labels){
        i->label->hide();
        i->label->is_dizhu_card=true;
    }

    for(int i=0;i<2;i++){
        playerLabels[i]->setName("玩家"+QString::number(i+1)+'\n'+"未准备");
        playerLabels[i]->hideNum();
        playerLabels[i]->hideBuChu();
        playerLabels[i]->hide();
    }

    cards.clear();
    card_labels.clear();

    // 设置指针为nullptr，以免delete出错

    // 随机选取一个玩家先开始
    srand(time(nullptr));
    playerIndex=(whoBegin=rand()%3);
    qDebug()<<"beginIndex: "<<whoBegin;

    ui->pushButton->hide();
    textOnShow->hide();
    qDebug()<<"init end...";
}

// 作为服务器端的出牌函数
void MainWindow::chuPaiSlot(){
    std::vector<Card> a;
    std::vector<Card> b;

    for(int i=0;i<(int)card_labels.size();i++){
        if(card_labels[i].selected)
            a.push_back(card_labels[i].card);
        else
            b.push_back(card_labels[i].card);
    }

    if(!a.size())return;

    Cards* newCards=new Cards(std::move(a));
    if(!newCards->valiable()){
        QMessageBox::information(this,"不可出","出的牌是不合法的",QMessageBox::Ok);
        delete newCards;return;
    }

    if(lastCards!=nullptr)
        if(lastCards->compare_smaller(*newCards)!=1){
            QMessageBox::information(this,"不可出","要出能盖过上家的牌",QMessageBox::Ok);
            delete newCards;
            return;
        }

    // 下面就说明这个牌可以出了，那么就替换掉lastCards，向两个客户端发信息，重新显示手牌和中间卡牌
    chuPai->hide();
    buChu->hide();
    hideBuChu();

    delete lastCards;
    lastCards=newCards;

    delete centerCards;
    centerCards = new CardOnShowQLabel(this,lastCards->getCards());

    cards=std::move(b);
    show_my_cards();

    playerLast=playerIndex;

    for(int i=0;i<2;i++){
        clients[i]->write((QString("setNum 0 ")+QString::number(cards.size())+';').toUtf8());
        QString out="setCard ";
        for(int ii=0;ii<(int)lastCards->getCards().size();ii++){
            out+=QString::number(lastCards->getCards()[ii].getPoint())+' ';
        }
        clients[i]->write((out+';').toUtf8());
    }

    checkGameWin();

    player_next();

    awakePlayer();
}

void MainWindow::chuPaiForClient(){
    std::vector<Card> a;
    std::vector<Card> b;

    for(int i=0;i<(int)card_labels.size();i++){
        if(card_labels[i].selected)
            a.push_back(card_labels[i].card);
        else
            b.push_back(card_labels[i].card);
    }

    if(!a.size())return;

    Cards* newCards=new Cards(std::move(a));
    if(!newCards->valiable()){
        QMessageBox::information(this,"不可出","出的牌是不合法的",QMessageBox::Ok);
        delete newCards;
        return;
    }

    if(lastCards!=nullptr)
        if(lastCards->compare_smaller(*newCards)!=1){
            QMessageBox::information(this,"不可出","要出能盖过上家的牌",QMessageBox::Ok);
            delete newCards;
            return;
        }

    // 下面就说明这个牌可以出了，那么就替换掉lastCards，向两个客户端发信息，重新显示手牌和中间卡牌
    chuPai->hide();
    buChu->hide();
    hideBuChu();

    delete lastCards;
    lastCards=newCards;

    delete centerCards;
    centerCards = new CardOnShowQLabel(this,lastCards->getCards());

    cards=std::move(b);
    show_my_cards();

    client->write((QString("setNum ")+QString::number(cards.size())+';').toUtf8());
    // 注意这里由于接受的逻辑，需要先setNum
    QString out="setCard ";
    for(int ii=0;ii<(int)lastCards->getCards().size();ii++){
        out+=QString::number(lastCards->getCards()[ii].getPoint())+' ';
    }
    client->write((out+';').toUtf8());
}

void MainWindow::buChuForClient(){
    chuPai->hide();
    buChu->hide();

    client->write("buChu;");
}

void MainWindow::hideBuChu(){
    playerLabels[0]->hideBuChu();
    playerLabels[1]->hideBuChu();
}

void MainWindow::buChuSlot(){
    chuPai->hide();
    buChu->hide();

    for(int i=0;i<2;i++)clients[i]->write("buChu 0;");

    player_next();
    awakePlayer();
}

// 检测现在游戏赢了没，如果赢了就设置diZhu_win的值并调用end(false)，并发送结束信息
void MainWindow::checkGameWin(){
    // 仅在服务器端用
    if(!cards.size()){
        qDebug()<<"dizhu: "<<dizhu;
        if(!dizhu)winner_dizhu=true;
        else winner_dizhu=false;
    }else if(!playerLabels[0]->getNum()){
        if(dizhu==1)winner_dizhu=true;
        else winner_dizhu=false;
    }else if(!playerLabels[1]->getNum()){
        if(dizhu==2)winner_dizhu=true;
        else winner_dizhu=false;
    }else return;

    state=MainWindow::ended;

    for(int i=0;i<3;can_restart[i++]=false);

    for(int i=0;i<2;i++)
        clients[i]->write((QString("end ")+QString::number(winner_dizhu)+';').toUtf8());

    end(false);
}

void MainWindow::restartSlot(){
    restart->hide();
    quit->hide();

    can_restart[0]=true;

    restartReally();
}

void MainWindow::restartReally(){
    for(int i=0;i<3;i++)
        if(!can_restart[i])return;

    init();

    state=MainWindow::for_dizhu;

    for(int i=0;i<2;i++){
        playerLabels[i]->setName(QString("玩家")+QString::number(i+1));
        playerLabels[i]->show();
        clients[i]->write("restart;");
    }

    playerIndex=whoBegin;

    distribute_cards();
    show_dizhu_cards_hidden();
    show_my_cards();

    dealDiZhu(false);
}

// 处理用户断线或者客户端被关掉
void MainWindow::disconnect(int index){
    // 游戏中断线
    if(state==MainWindow::for_dizhu||state==MainWindow::gaming||state==MainWindow::ended){
        // 这里给用户弹窗告诉断线了
        QMessageBox::information(this, "网络错误", "检测到用户断线，游戏将终止", QMessageBox::Ok);
        exit(0);
    }

    clients[index]=nullptr;
    is_ready[index+1]=false;

    // 结束阶段自然断线，什么都不做（不能这样，不然就可能造成单人重开）
    if(state==MainWindow::ended){
        qDebug()<<"client disconnected, number: "<<index;
        return;
    }

    // 下面的代码就是在未开始阶段的处理了
    state=MainWindow::waiting;
    ui->pushButton->hide();

    playerLabels[index]->setName("玩家"+QString::number(index+1)+'\n'+"未准备");
    playerLabels[index]->hideNum();
    playerLabels[index]->hide();

    if(clients[!index]!=nullptr){
        clients[!index]->write("player;");
    }
}

// 接受客户的新连接，并绑定到两个socket上面
void MainWindow::receiveNewConnect(){
    // 先接受了，以免以后重复接受
    QTcpSocket* client = server->nextPendingConnection();

    // 不允许非等待时间连接
    if(state!=MainWindow::waiting)return;

    int which=0;
    if(clients[0]==nullptr){
        clients[0]=client;
        connect(client,SIGNAL(disconnected()),this,SLOT(clientDisconnect1()));
        which=1;
        playerLabels[0]->show();
    }else if(clients[1]==nullptr){
        clients[1]=client;
        connect(client,SIGNAL(disconnected()),this,SLOT(clientDisconnect2()));
        which=2;
        playerLabels[1]->show();
    }else {qDebug()<<"超过两个人连接！不作出动作！";}

    if(which==1)connect(client, SIGNAL(readyRead()), this, SLOT(dealClient1()));
    else if(which==2)connect(client, SIGNAL(readyRead()), this, SLOT(dealClient2()));

    clients[which-1]->write((QString("index ")+QString::number(which)).toUtf8()+';');
    if(clients[!(which-1)]!=nullptr){
        clients[which-1]->write("player;");
        clients[!(which-1)]->write("player;");
        if(is_ready[!(which-1)+1])
            clients[which-1]->write("ready;");
    }

    // 两个客户端连接上就可以准备开始了
    if(clients[0]!=nullptr&&clients[1]!=nullptr){
        state=MainWindow::for_ready;

        // 还没有显示准备游戏的按钮
        // ui->pushButton->show();
    }
}

void MainWindow::dealPlayer(int index){
    if(state==MainWindow::waiting){dealForReady(index-1);return;}

    if(state==MainWindow::for_ready){dealForReady(index-1);return;}

    if(state==MainWindow::ended){
        QList<QString> argss=(QString(clients[index-1]->readAll())).split(';');
        qDebug()<<argss;

        for(auto command:argss){
            auto args=command.split(' ');

            if(args[0]=="restart"){
                can_restart[index]=true;
                restartReally();
            }
        }
        return;
    }

    // 上面是准备阶段的逻辑，下面的逻辑就需要发来的东西和现在可行动的相同了；若已结束也需避开
    if(playerIndex!=index){
        dealWaiting(index-1); // 但是也要读掉传来的内容
        return;
    }

    if(state==MainWindow::for_dizhu){dealForDiZhu();return;}

    //接下来就是处于游戏中的操作了
    QList<QString> argss=(QString(clients[playerIndex-1]->readAll())).split(';');
    qDebug()<<argss;

    for(auto command:argss){
        auto args=command.split(' ');

        if(args[0]=="buChu"){
            clients[!(index-1)]->write("buChu 1;");
            playerLabels[index-1]->showBuChu();
            player_next();
            awakePlayer();
        }else if(args[0]=="setCard"){
            hideBuChu();

            std::vector<Card> a;
            for(int i=1;i<args.size();i++)
                if(args[i].size())
                    a.emplace_back(Card(0,args[i].toInt()));

            delete centerCards;
            centerCards=new CardOnShowQLabel(this,a);

            delete lastCards;
            lastCards=new Cards(std::move(a));

            QString out="setCard ";
            for(int ii=0;ii<(int)lastCards->getCards().size();ii++){
                out+=QString::number(lastCards->getCards()[ii].getPoint())+' ';
            }
            clients[!(playerIndex-1)]->write((out+';').toUtf8());

            checkGameWin();

            playerLast=playerIndex;
            player_next();
            awakePlayer();
            // 两个的逻辑决定了setNum要先于setCard发出
        }else if(args[0]=="setNum"){
            // 给另一个发信息，改变显示的玩家框

            playerLabels[playerIndex-1]->setNum(args[1].toInt());

            clients[!(playerIndex-1)]->write((QString("setNum ")+
                                              QString::number(playerIndex)+
                                              ' '+args[1]+';').toUtf8());
        }
    }
}

void MainWindow::dealForDiZhu(){
    QList<QString> argss=(QString(clients[playerIndex-1]->readAll())).split(';');
    qDebug()<<argss;

    for(auto i:argss){
        auto args=i.split(' ');
        if(args[0]=="jiao"){
            diZhu[playerIndex]=true;
            playerLabels[playerIndex-1]->setName(QString("玩家")+QString::number(playerIndex)+'\n'+
                                                 "叫地主");
            clients[!(playerIndex-1)]->write((QString("jiao ")+QString::number(playerIndex)+';').toUtf8());
        }else if(args[0]=="buJiao"){
            diZhu[playerIndex]=false;
            playerLabels[playerIndex-1]->setName(QString("玩家")+QString::number(playerIndex)+'\n'+
                                                 "不叫");
            clients[!(playerIndex-1)]->write((QString("buJiao ")+QString::number(playerIndex)+';').toUtf8());
        }else continue;

        player_next();
        dealDiZhu(true);
    }
}

// 什么都不干，但是因为buffer会叠加，所以必须每次都读取
void MainWindow::dealWaiting(int index){
    QByteArray datagram;
    datagram.resize(clients[index]->bytesAvailable());
    clients[index]->read(datagram.data(),datagram.size());
    qDebug()<<"dealWaiting: "<<datagram;
}

void MainWindow::dealForReady(int index){
    // 为了保险，要判断是不是准备请求，是的话才改，并返回对应的信号
    QString datagram=clients[index]->readAll();
    qDebug()<<datagram;

    QList<QString> args=datagram.split(';');

    for(auto i:args)
        if(i=="ready")
            is_ready[index+1]=!is_ready[index+1];

    if(is_ready[index+1]){
        playerLabels[index]->setName("玩家"+QString::number(index+1)+'\n'+"已准备");
    }else playerLabels[index]->setName("玩家"+QString::number(index+1)+'\n'+"未准备");

    if(clients[!index]!=nullptr)
        clients[!index]->write("ready;");

    check_for_ready();
}

void MainWindow::check_for_ready(){
    for(int i=0;i<3;i++)
        if(!is_ready[i]){
            ui->pushButton->hide();
            return;
        }

    ui->pushButton->show();
}

/*
// 注意这个函数是要直接接受请求，处理之后返回东西的
void MainWindow::xuanDiZhu(int index){
    if(begin)return;

    bool diZhuBefore=false;
    for(int i=0;i<index;i++){
        if(diZhu[i])diZhuBefore=true;
    }
}
*/

void MainWindow::beginGame(){
    if(state!=MainWindow::for_ready)return;

    state=MainWindow::for_dizhu;

    ui->pushButton->hide();

    for(int i=0;i<2;i++)
        clients[i]->write("forDiZhu;");

    distribute_cards();

    show_dizhu_cards_hidden();
    show_my_cards();

    playerIndex=whoBegin;

    dealDiZhu(false);
}

void MainWindow::player_next(){
    if(playerIndex==2)playerIndex=0;
    else ++playerIndex;
}

void MainWindow::dealDiZhu(bool flag){
    if(state!=MainWindow::for_dizhu)return;

    // flag是用来判断绕回来要不要停下
    if(flag&&whoBegin==playerIndex){
        dizhu=-1;
        for(int i=0;i<3;i++){
            if(diZhu[playerIndex])
                dizhu=playerIndex;
            player_next();
        }
        if(dizhu==-1)dizhu=playerIndex;

        playerIndex=dizhu;

        startGame();

        return;
    }

    if(!playerIndex){
        beDiZhu->show();
        notDiZhu->show();
    }else{
        clients[playerIndex-1]->write("canBeDiZhu;");

        // 这里还不能让playerindex下滚，应该放到响应函数里
    }
}

void MainWindow::addDiZhuCards(){
    // 把遮住的地主牌展示出来
    for(auto card_:dizhu_card_labels){
        card_->label->setText((card_->card).getShowed().data());
    }

    if(dizhu==index_client){
        for(auto card_:dizhu_cards){
            cards.push_back(card_);
        }

        std::sort(cards.begin(),cards.end());

        show_my_cards();
    }
}

void MainWindow::setupGamingUI(){
    textOnShow->hide();

    if(dizhu==index_client){
        for(int i=0;i<2;i++){
            playerLabels[i]->setName("农民");
            playerLabels[i]->setNum(17);
        }
    }else if(!index_client){
        playerLabels[dizhu-1]->setName("地主");
        playerLabels[dizhu-1]->setNum(20);
        playerLabels[!(dizhu-1)]->setName("农民");
        playerLabels[!(dizhu-1)]->setNum(17);
    }else if(!dizhu){
        playerLabels[0]->setName("地主");
        playerLabels[1]->setName("农民");
        playerLabels[0]->setNum(20);
        playerLabels[1]->setNum(17);
    }else{
        playerLabels[1]->setName("地主");
        playerLabels[0]->setName("农民");
        playerLabels[1]->setNum(20);
        playerLabels[0]->setNum(17);
    }

    for(auto i :playerLabels){
        i->showNum();
    }
}

void MainWindow::startGame(){
    addDiZhuCards();

    for(int i=0;i<2;i++)
        clients[i]->write((QString("diZhuIs ")+QString::number(dizhu)+';').toUtf8());

    setupGamingUI();

    state=MainWindow::gaming;

    playerIndex=dizhu;
    playerLast=dizhu;       // 首轮不能不出

    awakePlayer();
}

void MainWindow::awakePlayer(){
    if(state!=MainWindow::gaming)return;

    if(playerIndex){
        clients[playerIndex-1]->write((QString("chuPai ")+
                                       QString::number((playerIndex==playerLast))+';').toUtf8());
        // 上面发的第二个参数如果是1则应当说明只能出牌

        return;
    }

    if(playerLast!=playerIndex)buChu->show();
    else{
        delete lastCards;
        lastCards=nullptr;
    }
    chuPai->show();
}

void MainWindow::end(bool is_disconnect){
    state=MainWindow::ended;

    // 不用delete连接的socket，因为qt会自动维护
    if(is_disconnect)exit(0);

    // 不是因为断线就弹出游戏结束的窗口
    QString content;
    /*
    if(winner_dizhu)content="地主";
    else content="农民";
    QMessageBox::information(this,"游戏结束","游戏结束，"+content+"胜利",QMessageBox::Ok);
    */
    if(winner_dizhu){
        if(index_client==dizhu)content="你赢了";
        else content="你输了";
    }else if(index_client==dizhu)content="你输了";
    else content="你赢了";
    QMessageBox::information(this,"游戏结束",content,QMessageBox::Ok);

    restart->show(); // 客户端也要参与决定重开
    quit->show();
}

// 这个函数还要负责和两个客户端的通信
void MainWindow::distribute_cards(){
    std::vector<Card> all_cards;
    for(int i=1;i<14;i++)
        for(int j=0;j<4;j++)
            all_cards.push_back(Card(j,i));
    all_cards.push_back(Card(0,14));
    all_cards.push_back(Card(0,15));

    // 打乱这些牌
    srand(time(nullptr));
    for(int i=0;i<54;i++)
        std::swap(all_cards[rand()%54],all_cards[rand()%54]);

    cards.clear();
    for(int i=0;i<17;i++)
        cards.push_back(std::move(all_cards[i]));

    for(int i=17;i<34;i++){
        clients[0]->write((QString("addCard ")+QString::number(all_cards[i].getPoint())+';').toUtf8());
    }
    clients[0]->write("end;");

    for(int i=34;i<51;i++){
        clients[1]->write((QString("addCard ")+QString::number(all_cards[i].getPoint())+';').toUtf8());
    }
    clients[1]->write("end;");

    QString out="diZhuCard ";
    for(int i=0;i<3;i++){
        dizhu_cards[i]=std::move(all_cards[i+51]);
        out+=QString::number(dizhu_cards[i].getPoint())+' ';
        dizhu_card_labels[i]->card=dizhu_cards[i];
    }
    out+=';';
    //QMessageBox::information(this,"debug-out",out,QMessageBox::Ok);
    for(int i=0;i<2;i++)
        clients[i]->write(out.toUtf8());
}

void MainWindow::show_dizhu_cards_hidden(){
    for(auto i : dizhu_card_labels){
        i->label->setText("");
        i->label->show();
    }
}

void MainWindow::show_my_cards(){
    std::sort(cards.begin(),cards.end());

    card_labels.clear();

    for(int i=0;i<(int)cards.size();i++){
        card_labels.emplace_back(LabeledCard(this,cards[i]));// push_back调用的是复制构造函数，所以不行

        card_labels[i].index=i;
        card_labels[i].label->setText(QString(cards[i].getShowed().c_str()));
        card_labels[i].label->setGeometry((cardWidth/2)*(i+1),height-cardHeight-cardPadding,
                                          cardWidth,cardHeight);
        card_labels[i].label->show();
    }
}

void MainWindow::reshowCard(int index){
    if(card_labels[index].selected){
        card_labels[index].label->setGeometry((cardWidth/2)*(index+1),
                                              height-cardHeight-cardPadding-cardHigherDistance,
                                              cardWidth,cardHeight);
    }else{
        card_labels[index].label->setGeometry((cardWidth/2)*(index+1),
                                              height-cardHeight-cardPadding,
                                              cardWidth,cardHeight);
    }

    if(index<(int)card_labels.size()-1){
        card_labels[index].label->stackUnder(card_labels[index+1].label);
    }
}

void MainWindow::jiaoDiZhuForClient(){
    beDiZhu->hide();
    notDiZhu->hide();

    if(state!=MainWindow::for_dizhu)return;

    textOnShow->setText("叫地主");
    textOnShow->show();

    client->write("jiao;");
}

void MainWindow::buJiaoForClient(){
    beDiZhu->hide();
    notDiZhu->hide();

    if(state!=MainWindow::for_dizhu)return;

    textOnShow->setText("不叫");
    textOnShow->show();

    client->write("buJiao;");
}

MainWindow::~MainWindow(){
    delete ui;
}
